# obj序列化工具
# ================
# 变量 | 类型 | required | 描述
# ----|------|----------|-----
# obj | Object | true  | 要转化的obj
# oneLeves[] | [[],[]] | false default [["id","type"],[]] | 一层自定义显示顺序
# mutiLeves[] | [[],[]] | false default [["tabs"],["style","components"]] | 多层自定义显示顺序
# excludes | Array | false default [] | 要排除的字段
# isRemainingOrderdByKey | boolean | false default false | 除 oneLeves,mutiLeves 数组中定义的顺序外的key按照字母顺序排序属性
# tabNumbs | int | false default 4 | 要缩进的空格数
#
# ## 需求
# 0. 去掉空属性值
# 1. 对于每个组件下面的一些属性优先显示： id, type
# 2. 所有只有一层的属性显示
# 3. 显示 style 属性
# 4. 显示 components 属性
# 5. 显示其他属性
# 6. 至少要允许配置两个参数：
#   1. 缩进的空格数，
#   2. 可以配置哪些属性在序列化结果中优先显示，
#   3. 可以配置按照字母顺序排序属性;
#
# ## 实现思路
# 1.[[indexs],[otherIndexs],[lastIndexs],[multis],[otherMultis],[lastMultis]] 按此顺序
# 2.循环步骤1数组 生成新的resultObj
# 3.如果其key对应的是数组或者对象 进行递归1,2步骤
# 4.返回

_ = require 'underscore'

converter =
  convertObj: (obj, oneLeves, mutiLeves, excludes, isRemainingOrderdByKey) ->
    if !obj or !_.isObject(obj)
      return obj
    oneLeves = oneLeves or [
      [
        'id'
        'type'
      ]
      []
    ]
    mutiLeves = mutiLeves or [
      [
        'header'
        'tabs'
        'itemswidth'
      ]
      [
        'style'
        'components'
      ]
    ]
    excludes = excludes or [
      '_id'
      '__v'
      '_ide'
    ]
    oldOneLeves = _.clone(oneLeves)
    oldMutiLeves = _.clone(mutiLeves)
    # 一层头中尾
    indexs = oneLeves[0] or []
    otherIndexs = []
    lastIndexs = oneLeves[1] or []
    # 多层头中尾
    multis = mutiLeves[0] or []
    otherMultis = []
    lastMultis = mutiLeves[1] or []
    # 拼装完成后的keys数组
    unionKeys = []
    resultObj = {}
    if excludes.length > 0
      for exclude of excludes
        delete obj[excludes[exclude]]
    # obj 删除了excluds之后的keys数组
    objKeys = _.keys(obj)
    for keyIndex of objKeys
      key = objKeys[keyIndex]
      valueOfKey = obj[key]
      # 删除空key
      if valueOfKey == null or _.isUndefined(valueOfKey) or _.isObject(valueOfKey) or _.isString(valueOfKey)
        if _.isEmpty(valueOfKey)
          delete obj[key]
          continue
      # push other keys
      if !_.contains(indexs, key) and !_.contains(lastIndexs, key) and !_.contains(multis, key) and !_.contains(lastMultis, key)
        if _.isObject(valueOfKey)
          otherMultis.push key
        else
          otherIndexs.push key
    # key首字母排序
    if isRemainingOrderdByKey
      otherIndexs.sort()
      otherMultis.sort()
    # 交集
    unionKeys = _.intersection(_.union(indexs, otherIndexs, lastIndexs, multis, otherMultis, lastMultis), _.keys(obj))
    for unionKeyIndex of unionKeys
      unionKey = unionKeys[unionKeyIndex]
      valueOfUnionKey = obj[unionKey]
      if _.isUndefined(valueOfUnionKey)
        continue
      resultObj[unionKey] = valueOfUnionKey
      if _.isArray(valueOfUnionKey)
        for vIndex of valueOfUnionKey
          resultObj[unionKey][vIndex] = @convertObj(valueOfUnionKey[vIndex], oldOneLeves, oldMutiLeves, excludes, isRemainingOrderdByKey)
      else if _.isObject(valueOfUnionKey)
        resultObj[unionKey] = @convertObj(valueOfUnionKey, oldOneLeves, oldMutiLeves, excludes, isRemainingOrderdByKey)
    resultObj
  convertObjToString: (obj, oneLeves, mutiLeves, excludes, isRemainingOrderdByKey, tabNumbs) ->
    obj = @convertObj(obj, oneLeves, mutiLeves, excludes, isRemainingOrderdByKey, isRemainingOrderdByKey)
    JSON.stringify obj, null, tabNumbs or 4

module.exports = converter
